#include <glf.h>
#include <glfwindow.h>

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    GLuint name;
    const char* source;
} Shader;

typedef struct
{
    Shader vertexShader;
    Shader fragmentShader;
    GLuint program;
} ShaderProgram;

static int LoadShaderSource(Shader* shader, const char* filename)
{
    FILE* f;
    size_t filesize;
    
    if(!shader){
        fprintf(stderr, "Error in function in LoadShaderSource: \"shader\" pointer is NULL.\n");
        return 0;
    }
    if(!shader->name){
        fprintf(stderr, "Error in function in LoadShaderSource: ShaderAssignName not called for \"shader\".\n");
        return 0;
    }

    f = fopen(filename, "r");
    if(!f){
        fprintf(stderr, "Error in function in LoadShaderSource: Couldn't open file %s for reading.\n",filename);
        return 0;
    }
    fseek(f, 0, SEEK_END);
    filesize = ftell(f);
    rewind(f);
    shader->source = malloc( sizeof(char) * (filesize+1));
    
    if(!shader->source){
        fprintf(stderr, "Error in function in LoadShader: Out of memory.\n");
        fclose(f);
        return 0;
    }
    
    fread(shader->source, sizeof(char), filesize, f);
    fclose(f);
    
    glShaderSource(shader->name, 1, &shader->source, filesize);
    
    return 1;
}

static int ShaderAssignName(Shader* shader, GLenum type)
{
    if(!shader){
        fprintf(stderr, "Error in function in ShaderAssignName: \"shader\" is NULL.\n");
        return 0;
    }
    if(shader->name){
        fprintf(stderr, "Error in function in ShaderAssignName: \"Shader\" must be deleted first.\n");
        return 0;
    }
    shader->name = glCreateShader(type);
    return 1;
}

static int CreateShader(Shader* shader, GLenum type, const char* sourcefile)
{

    if(!ShaderAssignName(shader, type))
        return 0;
    if(!LoadShaderSource(shader, sourcefile))
        return 0;    
}

int init(void)
{
	return 0;
}

static void think(void* userdata)
{
    int* hasinit = userdata;
    if(!*hasinit){
        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
        *hasinit = 1;
    }
}

static void render(void* userdata)
{
    /* swapping buffers is done by the mainloop implicitly */
    glClear(GL_COLOR_BUFFER_BIT);
}

static void resize(void* userdata)
{
    glViewport(0,0,glfGetWidth(),glfGetHeight());
}

int main(void)
{
    int hasinit = 0;
    
    glfConfigSetAttribute( glfMajorVersion, 3 );
    glfConfigSetAttribute( glfMinorVersion, 0 );
    glfConfigSetAttribute( glfMultiSampleLevel, 2 );
    glfConfigSetAttribute( glfContextFlags, glfContextForwardCompatible );
    
    if( !glfCreateWindow( "GLF Empty Example", 1024, 768 ) )
        return -1;
        
    glfSetCallBack(glfCallbackThink, think, &hasinit);
    glfSetCallBack(glfCallbackRender, render, NULL);
    glfSetCallBack(glfCallbackResize, resize, NULL);
    
    if( glfMainloop() )
        return -1;
        
    glfDestroyWindow();
    return 0;
}
